Skip to content

feat: TSR Device Feedback -> Rundown (SOFIE-311)#1731

Merged
Julusian merged 15 commits into
Sofie-Automation:mainfrom
bbc:feat/tsr-device-feedback
Jun 1, 2026
Merged

feat: TSR Device Feedback -> Rundown (SOFIE-311)#1731
Julusian merged 15 commits into
Sofie-Automation:mainfrom
bbc:feat/tsr-device-feedback

Conversation

@Julusian
Copy link
Copy Markdown
Member

About the Contributor

This pull request is posted on behalf of the BBC

Type of Contribution

This is a: Feature

New Behavior

RFC: #1670

Allow TSR devices to report events when external state changes occur. This triggers a new blueprints method to allow for custom handling of these state changes.

Events are batched to avoid flooding the bluerpints/job-worker with a large backlog of events to handle

Testing

  • I have added one or more unit tests for this PR
  • I have updated the relevant unit tests
  • No unit test changes are needed for this PR

Affected areas

Time Frame

Other Information

Status

  • PR is ready to be reviewed.
  • The functionality has been tested by the author.
  • Relevant unit tests has been added / updated.
  • Relevant documentation (code comments, system documentation) has been added / updated.

@Julusian Julusian added the Contribution from BBC Contributions sponsored by BBC (bbc.co.uk) label Apr 27, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 27, 2026

Review Change Stack

Walkthrough

Introduces end-to-end external-event reporting: peripheral devices send TSR events to Core, Core queues/merges studio jobs, publications compute per-device subscriptions from rundowns, playout jobs invoke blueprint onExternalEvent handlers, and the gateway wires device connections to subscription updates.

Changes

External events end-to-end

Layer / File(s) Summary
Peripheral API and studio queueing
meteor/server/api/peripheralDevice.ts, meteor/server/worker/worker.ts
reportExternalEvents endpoint validates device access and queues/merges studio OnExternalEvents jobs via QueueOrUpdateStudioJob.
External-event subscription publication
meteor/server/publications/externalEventSubscriptions.ts, meteor/server/publications/_publications.ts
New Meteor publication computes ExternalEventSubscriptionDocument records per device/type from active playlists and rundowns; uses deterministic ids for tsr subscriptions and optimized observers.
Job queue merge API and tests
meteor/server/worker/__tests__/jobQueue.test.ts, meteor/server/worker/jobQueue.ts, meteor/server/worker/worker.ts
Adds merge-or-enqueue behavior for queue tail jobs and tests verifying merge semantics and worker notification; exposes QueueOrUpdateStudioJob wrapper.
Blueprint types and contexts
packages/blueprints-integration/src/externalEvent.ts, .../src/context/*.ts, packages/blueprints-integration/src/api/showStyle.ts
Defines BlueprintExternalEvent/subscription types, IExternalEventContext and IPlayoutActionContext, re-exports, and adds onExternalEvent + externalEventSubscriptions declarations.
Core worker job types
packages/corelib/src/worker/studio.ts
Adds StudioJobs.OnExternalEvents and OnExternalEventsProps (events array).
Job-worker wiring
packages/job-worker/src/workers/studio/jobs.ts
Imports and registers the OnExternalEvents handler in the studio job dispatch map.
Gateway TSR handling & subscriptions
packages/playout-gateway/src/tsrHandler.ts, packages/playout-gateway/src/coreHandler.ts
Gateway subscribes to external-event subscriptions; TSR handler forwards stateEvent lists to Core and maintains per-device subscribed event sets (debounced).
Shared library RPC/types and pubsub
packages/shared-lib/src/peripheralDevice/externalEvents.ts, packages/shared-lib/src/peripheralDevice/methodsAPI.ts, packages/shared-lib/src/pubsub/peripheralDevice.ts, packages/shared-lib/package.json, packages/playout-gateway/package.json
Adds peripheral external-event types, reportExternalEvents RPC mapping, pubsub collection/type for external subscriptions, and updates timeline-state-resolver/nightly deps.

Sequence Diagram(s)

sequenceDiagram
    participant TSRGateway as TSR Gateway
    participant Core as Core Server
    participant JobQueue as Job Queue Manager
    participant Playout as Playout Worker
    participant Blueprint as ShowStyle Blueprint

    TSRGateway->>Core: reportExternalEvents(deviceId, events)
    Core->>Core: validate device token & studioId
    Core->>JobQueue: QueueOrUpdateStudioJob(OnExternalEvents, studioId, merge events)
    JobQueue->>JobQueue: merge with tail job or enqueue new
    JobQueue->>Playout: process OnExternalEvents job (studio)
    Playout->>Playout: enumerate active playlists & rundowns
    Playout->>Blueprint: onExternalEvent(context, persistentState, events[])
    Blueprint->>Playout: return (state changes, notes)
    Playout->>Playout: save persistent state & notifications
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

Contribution

Suggested reviewers

  • nytamin
  • jstarpl
  • justandras
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: TSR Device Feedback -> Rundown' clearly summarizes the main feature: enabling TSR devices to report feedback events to the rundown system.
Description check ✅ Passed The description adequately explains the feature: TSR devices can report external state change events, triggering a new blueprints method with event batching to prevent flooding.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 27, 2026

@Julusian
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 29, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Julusian Julusian marked this pull request as ready for review April 29, 2026 15:31
@Julusian
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 29, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Julusian
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 29, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (5)
packages/playout-gateway/package.json (1)

58-58: Verify feature-branch nightly resolver is intentional before merging to main.

Line 58 pins a feature-branch nightly (nightly-feat-tsr-device-feedback-20260429-145317-4079605bd.0). The dependency is used across 7 imports in playout-gateway (DevicesRegistry, MediaObject, DeviceOptionsAny, ActionExecutionResult, BaseRemoteDeviceIntegration, TSRDevicesManifestEntry, and AtemMediaPool types) and no conflicting TSR versions exist elsewhere in the repo. All imports use standard public API surface. If this PR lands on main, plan to switch to a nightly-main or release build once available.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/playout-gateway/package.json` at line 58, The dependency
"timeline-state-resolver" is pinned to a feature-branch nightly
("10.0.0-nightly-feat-tsr-device-feedback-20260429-145317-4079605bd.0") used by
imports DevicesRegistry, MediaObject, DeviceOptionsAny, ActionExecutionResult,
BaseRemoteDeviceIntegration, TSRDevicesManifestEntry, and AtemMediaPool; before
merging to main either replace that pinned feature-nightly with the intended
stable/nightly-main or a release version (or add a clear TODO and justification)
in package.json so main doesn't depend on a feature branch—update the version
string accordingly and run install/build to confirm no type or API breaks across
those seven import sites.
packages/job-worker/src/ingest/generationRundown.ts (1)

302-304: Add a focused regression test for this new persisted field.

This introduces new rundown persistence behavior; please add an ingest test asserting externalEventSubscriptions from blueprint output are stored and retrievable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/job-worker/src/ingest/generationRundown.ts` around lines 302 - 304,
Add a regression test that verifies the new persisted field
externalEventSubscriptions produced by the blueprint is saved and can be
retrieved: in the ingest test suite that exercises generationRundown (where
translateUserEditsFromBlueprint(...) and externalEventSubscriptions are passed
into the persistence call), create a blueprint output containing a non-empty
externalEventSubscriptions array, run the existing ingestion path, then query
the persisted rundown and assert the stored
rundown.rundown.externalEventSubscriptions strictly equals the blueprint value;
ensure the test covers both save and subsequent retrieval to catch regressions.
meteor/server/worker/jobQueue.ts (1)

364-402: Add focused tests for merge-vs-enqueue behavior.

Please add coverage for:

  1. merge into matching high-priority tail,
  2. enqueue when tail is different/null,
  3. no mutation of ordering across mixed job names.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@meteor/server/worker/jobQueue.ts` around lines 364 - 402, Add unit tests for
mergeOrQueueJob covering three scenarios: (1) when the last high-priority job
has the same name, verify that mergeOrQueueJob calls generateData with the
existing tail.spec.data, mutates tail.spec.data in-place, does not change
queue.jobsHighPriority length, and logs the merge (use mergeOrQueueJob and
inspect the queue returned by `#getOrCreateQueue` or access the queue object after
invoking); (2) when the tail is absent or has a different name, verify a new
JobEntry is pushed with id from getRandomString(), name equal to jobName and
data from generateData(null), that queue.metricsTotal.inc() is called and
`#notifyWorker` is invoked (spy/mock generateData, getRandomString,
metricsTotal.inc, and `#notifyWorker`); (3) when multiple job names exist verify
ordering is preserved (calls that merge should only affect the very last entry
and must not reorder earlier entries) by setting up a queue.jobsHighPriority
array with mixed named entries, calling mergeOrQueueJob and asserting only the
tail changed or a new entry appended. Use spies/mocks for generateData and
minimal assertions on queue.jobsHighPriority length, element identities, and
tail.spec.data to ensure no unintended reordering or replacement.
meteor/server/worker/worker.ts (1)

254-265: Align startup-test guard with QueueStudioJob.

QueueStudioJob blocks during startup tests (isInTestWrite()), but this new path does not. Keeping the same guard avoids accidental writes in test bootstrap flows.

Suggested fix
 export function QueueOrUpdateStudioJob<T extends keyof StudioJobFunc>(
 	jobName: T,
 	studioId: StudioId,
 	generateData: (existing: Parameters<StudioJobFunc[T]>[0] | null) => Parameters<StudioJobFunc[T]>[0]
 ): void {
+	if (isInTestWrite()) throw new Meteor.Error(404, 'Should not be reachable during startup tests')
 	if (!studioId) throw new Meteor.Error(500, 'Missing studioId')
 	queueManager.mergeOrQueueJob(
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@meteor/server/worker/worker.ts` around lines 254 - 265, Add the same
startup-test guard used in QueueStudioJob to QueueOrUpdateStudioJob: at the top
of QueueOrUpdateStudioJob check isInTestWrite() and return early (no-op) when
true to avoid test-time writes; ensure the guard runs before any throws or calls
to queueManager.mergeOrQueueJob and keep the existing studioId null check and
mergeOrQueueJob call intact (function names: QueueOrUpdateStudioJob,
QueueStudioJob, isInTestWrite, queueManager.mergeOrQueueJob).
packages/job-worker/src/playout/externalEvents.ts (1)

109-113: Documented type cast acknowledged; consider runtime guard.

The comment explains that PeripheralDeviceExternalTSREvent uses a loose deviceType: string to accommodate custom TSR plugins, while BlueprintExternalTSREvent uses the strongly-typed TSR enum. The cast through unknown is intentional but bypasses compile-time type checking.

If a future event source (non-TSR) is added, this blanket cast could silently allow mismatched shapes into the blueprint. Consider adding a lightweight runtime assertion (e.g., verifying event.type === 'tsr') to fail fast on unexpected event types.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/job-worker/src/playout/externalEvents.ts` around lines 109 - 113,
The blanket cast from wireEvents to BlueprintExternalEvent[] (wireEvents ->
blueprintEvents) can hide mismatched shapes; add a lightweight runtime guard
before or during the cast that asserts each event is a TSR event (e.g., verify
event.type === 'tsr' for all entries in wireEvents) and either filter out
non-TSR events or throw a clear error; update the code around the
blueprintEvents assignment (the wireEvents variable and the resulting
blueprintEvents) to perform this check and fail fast if an unexpected event type
is encountered, while keeping the documented cast for deviceType handling
(PeripheralDeviceExternalTSREvent -> BlueprintExternalEvent).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@meteor/server/api/peripheralDevice.ts`:
- Around line 316-337: reportExternalEvents currently appends unbounded incoming
events into the pending StudioJobs.OnExternalEvents job, which can grow without
limit under bursts; update the reportExternalEvents handler to validate each
incoming PeripheralDeviceExternalEvent (type/required fields) and enforce a hard
maximum batch size before merging (e.g. define a MAX_EVENTS_PER_JOB constant),
then when calling QueueOrUpdateStudioJob merge sanitized events and truncate the
resulting array to that maximum (choose a policy: drop oldest or newest) so the
stored job data cannot grow unbounded; reference the reportExternalEvents
function, StudioJobs.OnExternalEvents and QueueOrUpdateStudioJob when making the
change.

In `@meteor/server/publications/externalEventSubscriptions.ts`:
- Around line 163-166: Add runtime validation for the `type` parameter in the
same function that currently does `check(deviceId, String)` (in
meteor/server/publications/externalEventSubscriptions.ts) by calling
`check(type, String)` before using `type` to filter subscription documents and
construct the observer key (e.g., where `peripheralDevice` is obtained via
`checkAccessAndGetPeripheralDevice`); this ensures `type` is a string and
prevents invalid values from affecting the publication observer behavior.

In `@packages/job-worker/src/playout/externalEvents.ts`:
- Around line 118-124: The category string passed into
storeNotificationsForCategory currently uses getRandomId()
("externalEvent:${getRandomId()}"), causing a new category on every call and
unbounded notification growth; change the category to a deterministic identifier
(for example "externalEvent:${playlist.playlistId}" or
"externalEvent:${playlist.rundownId}" or include blueprint.blueprintId) so
repeated external-event calls overwrite the same category. Locate the call to
storeNotificationsForCategory in externalEvents.ts and replace the getRandomId()
suffix with a stable field from the playlist or rundown (using
playlist.playlistId, playlist.rundownId, or blueprint.blueprintId) so
notifications are replaced instead of accumulated.

In `@packages/playout-gateway/src/tsrHandler.ts`:
- Around line 873-910: The _updateEventSubscriptions method only runs on DB
collection changes, so add listeners to the TSR connection manager to refresh
subscriptions whenever connection topology changes: in the class initialization
(where tsr is available) subscribe to the connection manager's
connection-added/connection-removed/connection-updated (or equivalent) events
and call this._updateEventSubscriptions() when those fire (also handle cases
where a connection's deviceId changes); ensure you remove those listeners on
teardown. Reference the existing _updateEventSubscriptions method and
tsr.connectionManager.getConnections()/container.device to locate where to wire
the event handlers.

---

Nitpick comments:
In `@meteor/server/worker/jobQueue.ts`:
- Around line 364-402: Add unit tests for mergeOrQueueJob covering three
scenarios: (1) when the last high-priority job has the same name, verify that
mergeOrQueueJob calls generateData with the existing tail.spec.data, mutates
tail.spec.data in-place, does not change queue.jobsHighPriority length, and logs
the merge (use mergeOrQueueJob and inspect the queue returned by
`#getOrCreateQueue` or access the queue object after invoking); (2) when the tail
is absent or has a different name, verify a new JobEntry is pushed with id from
getRandomString(), name equal to jobName and data from generateData(null), that
queue.metricsTotal.inc() is called and `#notifyWorker` is invoked (spy/mock
generateData, getRandomString, metricsTotal.inc, and `#notifyWorker`); (3) when
multiple job names exist verify ordering is preserved (calls that merge should
only affect the very last entry and must not reorder earlier entries) by setting
up a queue.jobsHighPriority array with mixed named entries, calling
mergeOrQueueJob and asserting only the tail changed or a new entry appended. Use
spies/mocks for generateData and minimal assertions on queue.jobsHighPriority
length, element identities, and tail.spec.data to ensure no unintended
reordering or replacement.

In `@meteor/server/worker/worker.ts`:
- Around line 254-265: Add the same startup-test guard used in QueueStudioJob to
QueueOrUpdateStudioJob: at the top of QueueOrUpdateStudioJob check
isInTestWrite() and return early (no-op) when true to avoid test-time writes;
ensure the guard runs before any throws or calls to queueManager.mergeOrQueueJob
and keep the existing studioId null check and mergeOrQueueJob call intact
(function names: QueueOrUpdateStudioJob, QueueStudioJob, isInTestWrite,
queueManager.mergeOrQueueJob).

In `@packages/job-worker/src/ingest/generationRundown.ts`:
- Around line 302-304: Add a regression test that verifies the new persisted
field externalEventSubscriptions produced by the blueprint is saved and can be
retrieved: in the ingest test suite that exercises generationRundown (where
translateUserEditsFromBlueprint(...) and externalEventSubscriptions are passed
into the persistence call), create a blueprint output containing a non-empty
externalEventSubscriptions array, run the existing ingestion path, then query
the persisted rundown and assert the stored
rundown.rundown.externalEventSubscriptions strictly equals the blueprint value;
ensure the test covers both save and subsequent retrieval to catch regressions.

In `@packages/job-worker/src/playout/externalEvents.ts`:
- Around line 109-113: The blanket cast from wireEvents to
BlueprintExternalEvent[] (wireEvents -> blueprintEvents) can hide mismatched
shapes; add a lightweight runtime guard before or during the cast that asserts
each event is a TSR event (e.g., verify event.type === 'tsr' for all entries in
wireEvents) and either filter out non-TSR events or throw a clear error; update
the code around the blueprintEvents assignment (the wireEvents variable and the
resulting blueprintEvents) to perform this check and fail fast if an unexpected
event type is encountered, while keeping the documented cast for deviceType
handling (PeripheralDeviceExternalTSREvent -> BlueprintExternalEvent).

In `@packages/playout-gateway/package.json`:
- Line 58: The dependency "timeline-state-resolver" is pinned to a
feature-branch nightly
("10.0.0-nightly-feat-tsr-device-feedback-20260429-145317-4079605bd.0") used by
imports DevicesRegistry, MediaObject, DeviceOptionsAny, ActionExecutionResult,
BaseRemoteDeviceIntegration, TSRDevicesManifestEntry, and AtemMediaPool; before
merging to main either replace that pinned feature-nightly with the intended
stable/nightly-main or a release version (or add a clear TODO and justification)
in package.json so main doesn't depend on a feature branch—update the version
string accordingly and run install/build to confirm no type or API breaks across
those seven import sites.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6b94813a-bfd3-48dc-b4e5-06cef5485324

📥 Commits

Reviewing files that changed from the base of the PR and between bb2a27d and 58dd4f0.

⛔ Files ignored due to path filters (2)
  • meteor/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
  • packages/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (28)
  • meteor/server/api/peripheralDevice.ts
  • meteor/server/publications/_publications.ts
  • meteor/server/publications/externalEventSubscriptions.ts
  • meteor/server/publications/rundown.ts
  • meteor/server/worker/jobQueue.ts
  • meteor/server/worker/worker.ts
  • packages/blueprints-integration/src/api/showStyle.ts
  • packages/blueprints-integration/src/context/adlibActionContext.ts
  • packages/blueprints-integration/src/context/externalEventContext.ts
  • packages/blueprints-integration/src/context/index.ts
  • packages/blueprints-integration/src/context/playoutActionContext.ts
  • packages/blueprints-integration/src/externalEvent.ts
  • packages/blueprints-integration/src/index.ts
  • packages/corelib/src/dataModel/Rundown.ts
  • packages/corelib/src/worker/studio.ts
  • packages/job-worker/src/ingest/generationRundown.ts
  • packages/job-worker/src/ingest/model/IngestModel.ts
  • packages/job-worker/src/ingest/model/implementation/IngestModelImpl.ts
  • packages/job-worker/src/playout/adlibAction.ts
  • packages/job-worker/src/playout/externalEvents.ts
  • packages/job-worker/src/workers/studio/jobs.ts
  • packages/playout-gateway/package.json
  • packages/playout-gateway/src/coreHandler.ts
  • packages/playout-gateway/src/tsrHandler.ts
  • packages/shared-lib/package.json
  • packages/shared-lib/src/peripheralDevice/externalEvents.ts
  • packages/shared-lib/src/peripheralDevice/methodsAPI.ts
  • packages/shared-lib/src/pubsub/peripheralDevice.ts

Comment thread meteor/server/api/peripheralDevice.ts
Comment thread meteor/server/publications/externalEventSubscriptions.ts
Comment thread packages/job-worker/src/playout/externalEvents.ts
Comment thread packages/playout-gateway/src/tsrHandler.ts
@Julusian Julusian changed the title TSR Device Feedback -> Rundown (SOFIE-311) feat: TSR Device Feedback -> Rundown (SOFIE-311) Jun 1, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/shared-lib/src/pubsub/peripheralDevice.ts (1)

140-144: 💤 Low value

Parameter ordering diverges from the other subscription signatures.

Every other entry in PeripheralDevicePubSubTypes leads with deviceId (e.g. mountedTriggersForDevice, packageManagerExpectedPackages). This new entry places type before deviceId. It works (the gateway calls it as ('tsr', deviceId)), but the inconsistency is easy to trip over. Consider leading with deviceId for consistency.

♻️ Proposed reordering (requires updating callers)
 	[PeripheralDevicePubSub.externalEventSubscriptionsForDevice]: (
-		type: PeripheralDeviceExternalEvent['type'],
 		deviceId: PeripheralDeviceId,
+		type: PeripheralDeviceExternalEvent['type'],
 		token?: string
 	) => PeripheralDevicePubSubCollectionsNames.externalEventSubscriptions

Caller in packages/playout-gateway/src/coreHandler.ts would change to autoSubscribe(..., this.core.deviceId, 'tsr').

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/shared-lib/src/pubsub/peripheralDevice.ts` around lines 140 - 144,
The new subscription signature
PeripheralDevicePubSub.externalEventSubscriptionsForDevice places the event type
parameter before deviceId, diverging from other subscriptions that lead with
deviceId; change the signature to (deviceId: PeripheralDeviceId, type:
PeripheralDeviceExternalEvent['type'], token?: string) =>
PeripheralDevicePubSubCollectionsNames.externalEventSubscriptions and update all
callers (e.g., the autoSubscribe invocation in coreHandler.ts) to pass
this.core.deviceId first and the event type second so the parameter order
matches mountedTriggersForDevice and packageManagerExpectedPackages.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/shared-lib/src/pubsub/peripheralDevice.ts`:
- Around line 140-144: The new subscription signature
PeripheralDevicePubSub.externalEventSubscriptionsForDevice places the event type
parameter before deviceId, diverging from other subscriptions that lead with
deviceId; change the signature to (deviceId: PeripheralDeviceId, type:
PeripheralDeviceExternalEvent['type'], token?: string) =>
PeripheralDevicePubSubCollectionsNames.externalEventSubscriptions and update all
callers (e.g., the autoSubscribe invocation in coreHandler.ts) to pass
this.core.deviceId first and the event type second so the parameter order
matches mountedTriggersForDevice and packageManagerExpectedPackages.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a41ded80-0ece-4244-98f0-32676d414ca0

📥 Commits

Reviewing files that changed from the base of the PR and between 58dd4f0 and aa72256.

⛔ Files ignored due to path filters (1)
  • meteor/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (14)
  • meteor/server/api/peripheralDevice.ts
  • meteor/server/publications/externalEventSubscriptions.ts
  • meteor/server/worker/__tests__/jobQueue.test.ts
  • meteor/server/worker/worker.ts
  • packages/blueprints-integration/src/api/showStyle.ts
  • packages/blueprints-integration/src/context/index.ts
  • packages/corelib/src/worker/studio.ts
  • packages/job-worker/src/workers/studio/jobs.ts
  • packages/playout-gateway/package.json
  • packages/playout-gateway/src/coreHandler.ts
  • packages/playout-gateway/src/tsrHandler.ts
  • packages/shared-lib/package.json
  • packages/shared-lib/src/peripheralDevice/methodsAPI.ts
  • packages/shared-lib/src/pubsub/peripheralDevice.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/blueprints-integration/src/context/index.ts
🚧 Files skipped from review as they are similar to previous changes (11)
  • packages/shared-lib/package.json
  • packages/playout-gateway/package.json
  • packages/playout-gateway/src/coreHandler.ts
  • packages/job-worker/src/workers/studio/jobs.ts
  • packages/corelib/src/worker/studio.ts
  • meteor/server/worker/worker.ts
  • packages/blueprints-integration/src/api/showStyle.ts
  • packages/shared-lib/src/peripheralDevice/methodsAPI.ts
  • packages/playout-gateway/src/tsrHandler.ts
  • meteor/server/api/peripheralDevice.ts
  • meteor/server/publications/externalEventSubscriptions.ts

@Julusian Julusian merged commit c580d76 into Sofie-Automation:main Jun 1, 2026
24 checks passed
@Julusian Julusian deleted the feat/tsr-device-feedback branch June 1, 2026 10:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Contribution from BBC Contributions sponsored by BBC (bbc.co.uk)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants